import os
import fnmatch
import sys
from pathlib import Path
from datetime import datetime

def merge_code_to_txt(input_dir, output_file):
    """
    将目录中的代码文件合并到单个txt文件中
    针对 Windows 系统和 JS/TS 项目进行了优化

    参数:
        input_dir (str): 要扫描的源代码目录
        output_file (str): 合并后的输出文件路径
    """
    # 允许的文件扩展名（JS/TS项目）
    allowed_ext = ('.js', '.ts', '.jsx', '.tsx', '.vue', '.css', '.scss', '.less', '.json', '.html', '.md')

    # 需要忽略的目录（JS/TS项目特有）
    ignore_dirs = {
        'node_modules', '.git', '.vscode', '.idea', 'dist', 'build',
        'coverage', '__tests__', '__mocks__', '__snapshots__', 'cache',
        'release', '.erb', 'txtdata'  # 添加了 release 和 txtdata 目录
    }

    # 需要忽略的文件模式（JS/TS项目特有）
    ignore_files = {
        'package-lock.json', 'yarn.lock', '.env*', '.eslint*', '.prettier*',
        '*.log', '*.min.js', '*.min.css', '*.spec.*', '.test.*', '*.d.ts',
        'tsconfig.json', 'webpack.config.*', 'babel.config.*', 'jest.config.*',
        'del.js', 'tailwind.config.js', 'package.json', 'README.*', 'LICENSE'
    }

    # 文件分隔线（80个等号）
    separator = '\n' + '=' * 80 + '\n'

    # 打印启动信息
    print(f"Starting code merge for JS/TS project in: {input_dir}")
    print(f"Ignoring directories: {', '.join(ignore_dirs)}")
    print(f"Ignoring file patterns: {', '.join(ignore_files)}")

    # 检查输入目录是否存在
    if not os.path.exists(input_dir):
        print(f"错误: 目录 '{input_dir}' 不存在!")
        print(f"当前工作目录: {os.getcwd()}")
        print(f"请检查路径是否正确")
        return

    # 打印目录验证信息
    print(f"目录验证: {input_dir} 存在")
    print(f"目录内容示例: {os.listdir(input_dir)[:5]}")  # 显示前5个文件/目录

    # 初始化计数器
    processed_files = 0
    skipped_files = 0

    # 打开输出文件（使用 utf-8 编码）
    with open(output_file, 'w', encoding='utf-8') as out_f:
        # 添加项目信息头
        out_f.write(f"JS/TS PROJECT CODE MERGE\n")
        out_f.write(f"Source Directory: {input_dir}\n")
        out_f.write(f"Generated at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n")

        # 遍历目录树
        for root, dirs, files in os.walk(input_dir):
            # 在遍历过程中忽略指定目录（提高效率）
            # 注意：修改 dirs 列表会影响后续的遍历
            dirs[:] = [d for d in dirs if d not in ignore_dirs]

            # 打印当前遍历的目录
            print(f"扫描目录: {root}")

            # 处理当前目录中的文件
            for file in files:
                # 构建完整的文件路径
                file_path = Path(root) / file

                # 获取文件的相对路径（相对于输入目录）
                try:
                    rel_path = file_path.relative_to(input_dir)
                except ValueError:
                    rel_path = file_path  # 如果无法计算相对路径，则使用绝对路径

                # 检查文件扩展名是否在允许列表中
                ext_ok = any(file.lower().endswith(ext) for ext in allowed_ext)

                # 检查文件是否匹配忽略模式 - 修复这里的语法错误
                ignore = any(fnmatch.fnmatch(file, pattern) for pattern in ignore_files)

                # 如果文件不符合条件，跳过
                if not ext_ok or ignore:
                    reason = "扩展名不在允许列表中" if not ext_ok else "匹配忽略模式"
                    print(f"  跳过文件: {rel_path} ({reason})")
                    skipped_files += 1
                    continue

                try:
                    # 写入分隔线和文件名
                    out_f.write(f"{separator}File: {rel_path}\n{separator}")

                    # 写入文件内容
                    with open(file_path, 'r', encoding='utf-8') as in_f:
                        content = in_f.read()
                        out_f.write(content)
                        out_f.write('\n\n')  # 文件末尾添加空行

                    # 更新计数器并打印进度
                    processed_files += 1
                    print(f"  已处理: {rel_path}")

                except UnicodeDecodeError:
                    # 处理编码错误（可能是二进制文件）
                    print(f"  跳过二进制文件: {rel_path}")
                    skipped_files += 1
                except Exception as e:
                    # 处理其他可能的错误
                    print(f"  处理文件 {rel_path} 时出错: {str(e)}")
                    skipped_files += 1

    # 打印最终统计信息
    print(f"\n合并完成! 已处理 {processed_files} 个文件, 跳过 {skipped_files} 个文件。")
    print(f"输出文件: {output_file}")

if __name__ == "__main__":
    # 配置路径 - 使用绝对路径确保可靠性
    # 注意：根据您的目录结构，源代码目录是项目根目录下的 'src' 文件夹
    desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
    project_root = os.path.join(desktop_path, "codes", "stock-electron")
    source_dir = os.path.join(project_root, "src")  # 源代码目录
    output_txt = os.path.join(project_root, "merged_js_code.txt")  # 输出文件

    # 打印路径信息以便验证
    print(f"项目根目录: {project_root}")
    print(f"源代码目录: {source_dir}")
    print(f"输出文件: {output_txt}")

    # 确保路径存在
    if not os.path.exists(source_dir):
        print(f"错误: 源代码目录 '{source_dir}' 不存在!")
        print("请检查路径配置")
        sys.exit(1)

    # 执行合并操作
    merge_code_to_txt(source_dir, output_txt)
